﻿#region Copyright and Licensing Notice
// Copyright (C) 2011 Steven Bosnick
// 
// This program is open source software; you can redistribute it 
// and/or modifiy it under the terms of the Eclipse Public License,
// version 1.0.
// 
// This program is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A 
// PARTICULAR PURPOSE. See the Eclipse Public License for more
// details.
// 
// You should have received a copy of the Eclipse Public License 
// along with this program; if not, you can find a copy at
// "http://www.opensource.org/licenses/eclipse-1.0.php".
#endregion
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using Autofac;
using Autofac.Core;
using BitwiseOre.SharedMemory.Context;
using BitwiseOre.SharedMemory.Core;
using BitwiseOre.SharedMemory.Core.Common;
using BitwiseOre.SharedMemory.Core.IPCQueues;
using BitwiseOre.SharedMemory.Core.Primatives;
using Module = Autofac.Module;

namespace BitwiseOre.SharedMemory.Autofac
{
    internal sealed class CoreModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
                .InNamespace("BitwiseOre.SharedMemory.Core")
                .Where(t => !t.IsDefined(typeof (SharedFactoryAttribute), false) &&
                            !t.IsDefined(typeof (CompilerGeneratedAttribute), false))
                .WithParameter(
                    (pi, c) => pi.ParameterType.IsInNamespaceOf<Acceptor>() &&
                               pi.ParameterType.Name.EndsWith("Config"),
                    (pi, c) => c.ResolveConfig(pi.ParameterType))
                .OnActivating(OnSharedObjectActivating)
                .AsSharedInterfaces();

            RegisterFactoryForType<ConnectionQueues>(builder);
            RegisterFactoryForType<ListenerQueue>(builder);
            RegisterFactoryForType<ConnectionBuffers>(builder);
            RegisterFactoryForType<GuidQueue>(builder);
        }

        private static void RegisterFactoryForType<T>(ContainerBuilder builder)
        {
            builder.Register((c, p) => c.Resolve<ISharedFactory<T>>(p).Create())
                .OnActivating(OnSharedObjectActivating)
                .InstancePerLifetimeScope()
                .As(typeof (T).GetInterfaces().Where(t => t != typeof (ISharedObjectInit)).ToArray());
        }

        private static void OnSharedObjectActivating<T>(IActivatingEventArgs<T> eventArgs)
        {
            var sharedobject = eventArgs.Instance as ISharedObjectInit;
            if (sharedobject == null) return;

            switch (eventArgs.Context.ResolveConfig<ISharedObjectConfig>().Status)
            {
            case SharedObjectStatus.CreateNew:
                sharedobject.InitializeNew();
                break;
            case SharedObjectStatus.OpenExisting:
                sharedobject.InitializeExisting();
                break;
            default:
                throw new ArgumentOutOfRangeException();
            }
        }
    }
}